#include "quicktimer.h"

QuickTimer::QuickTimer(QDialog *parent) : QDialog(parent){
    this->alarmMessageActive = false;
    this->sound = new QSound("sound.wav");
    this->sound->setLoops(-1);

    this->trayMessageIcon = QSystemTrayIcon::MessageIcon(1);
    for (int i = 0; i < 12; i++)
    {
	QString fileName = ":/src/";
	fileName.append(QString::number(i));
	fileName.append(".png");
	this->trayIcons[i] = QIcon(fileName);
    }

    this->readSettings();

    setupUi(this);

    this->createActions();
    this->createTrayIcon();
    this->createConnections();

    this->trayIcon->show();

    setWindowIcon(this->trayIcons[0]);

    lastSeperator = 0;
}

QuickTimer::~QuickTimer(){
}

void QuickTimer::showCreateAlarm()
{
    this->setAlarmTimeLabel();

    this->clockRefreshTimer.start(100, this);

    this->alarmMessagePreviousComboBox->clear();
    this->alarmMessagePreviousComboBox->addItems(this->alarmMessageList);
    this->alarmMessageLineEdit->setText(this->alarmMessageList.at(0));

    this->alarmMessageLineEdit->setFocus();
    this->alarmMessageLineEdit->selectAll();

    show();
    this->activateWindow();
}

void QuickTimer::setAlarmTimeLabel()
{
    QTime alarmTime = this->calcAlarmTime();

    this->alarmTimeLabel->setText(alarmTime.toString("hh:mm"));
}

QTime QuickTimer::calcAlarmTime()
{
    QTime currentTime = QTime::currentTime();
    int hours = this->alarmTimeHourSpinBox->value();
    int minutes = this->alarmTimeMinuteSpinBox->value();

    QTime alarmTime = currentTime.addSecs(hours * 60 * 60);
    alarmTime = alarmTime.addSecs(minutes * 60);

    return alarmTime;
}

void QuickTimer::createNewAlarm()
{
    Alarm *alarm = new Alarm();

    QTime alarmTime = this->calcAlarmTime();
    alarm->setAlarmTime(alarmTime);

    QString alarmMessage = this->alarmMessageLineEdit->text();

    for (int i = 0; i < this->alarmMessageList.size(); i++)
    {
        if (alarmMessage == alarmMessageList.at(i))
        {
            alarmMessageList.removeAt(i);
            break;
        }
    }
    this->alarmMessageList.push_front(alarmMessage);
    if (this->alarmMessageList.size() > 20)
        this->alarmMessageList.removeLast();
    alarm->setMessage(alarmMessage);

    QString actionString = alarmTime.toString("hh:mm");
    if (!alarmMessage.isEmpty())
    {
	actionString.append(" - ");
	actionString.append(alarmMessage.left(20));
    }
    QAction *alarmAction = new QAction(actionString, this);
    connect(trayIconMenu, SIGNAL(triggered(QAction *)), this, SLOT(removeMenuAction(QAction *)));
    alarm->setAction(alarmAction);

    alarmList.append(alarm);
    alarm->start(QTime::currentTime().msecsTo(alarmTime), this);
    //alarm->start(1000, this);

    if (lastSeperator)
	this->trayIconMenu->removeAction(lastSeperator);
    this->trayIconMenu->insertAction(this->newAlarmAction, alarmAction);
    this->lastSeperator = this->trayIconMenu->insertSeparator(this->newAlarmAction);

    this->writeSettings();

    this->closeNewAlarm();
}

void QuickTimer::removeMenuAction(QAction *action)
{
    for (int i = 0; i < alarmList.size(); i++)
    {
        Alarm *alarm = alarmList.at(i);
        if (alarm->getAction() == action)
        {
            alarm->stop();
            this->alarmList.removeAt(i);
            this->trayIconMenu->removeAction(action);
            this->setTrayIcon();
            break;
        }
    }
}

void QuickTimer::timerEvent(QTimerEvent *event)
{
    int timerId = event->timerId();
    if (timerId == clockRefreshTimer.timerId())
    {
        // clock refresh
        this->setAlarmTimeLabel();
    }
    else if (timerId == trayAnimationTimer.timerId())
    {
	// tray animation
	this->trayIcon->setIcon(this->trayIcons[this->trayAnimationIconIndex]);
	this->trayAnimationIconIndex++;
	if (this->trayAnimationIconIndex > 11)
	    this->trayAnimationIconIndex = 0;
    }
    else
    {
        // alarms
        for (int i = 0; i < alarmList.size(); i++)
        {
            Alarm *alarm = alarmList.at(i);
            if (alarm->timerId() == event->timerId())
            {
                alarm->stop();
                this->alarmList.removeAt(i);
                this->alarmEventList.append(alarm);
		this->sound->play();
		if (!alarmMessageActive)
                    this->processNextAlarmEvent();
                break;
            }
        }
    }
}

void QuickTimer::processNextAlarmEvent()
{
    if (alarmEventList.isEmpty())
    {
        alarmMessageActive = false;
    }
    else
    {
        alarmMessageActive = true;
        currentAlarmEvent = alarmEventList.first();
        alarmEventList.removeFirst();

        this->trayIconMenu->removeAction(currentAlarmEvent->getAction());

        QString message = currentAlarmEvent->getMessage();
        this->trayIcon->showMessage("Alarm", message, trayMessageIcon, 100000);
    }
    this->setTrayIcon();
}

void QuickTimer::showCurrentAlarmEvent()
{
    QString message = currentAlarmEvent->getMessage();
    this->trayIcon->showMessage("Alarm", message, trayMessageIcon, 100000);
}

void QuickTimer::cancelNewAlarm()
{
    this->closeNewAlarm();
}

void QuickTimer::closeNewAlarm()
{
    this->clockRefreshTimer.stop();
    this->updateToolTip();
    hide();
}

void QuickTimer::createActions()
{
    this->newAlarmAction = new QAction(tr("&New Alarm..."), this);
    connect(newAlarmAction, SIGNAL(triggered()), this, SLOT(showCreateAlarm()));

    this->quitAction = new QAction(tr("&Quit"), this);
    connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
}

void QuickTimer::createTrayIcon()
{
    this->trayIconMenu = new QMenu(this);

    this->trayIconMenu->addAction(newAlarmAction);
    this->trayIconMenu->addSeparator();
    this->trayIconMenu->addAction(quitAction);

    this->trayIcon = new QSystemTrayIcon(this);
    this->trayIcon->setContextMenu(trayIconMenu);

    this->setTrayIcon();
}

void QuickTimer::createConnections()
{
    connect(this->trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
                this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
    connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(messageClicked()));
    connect(this->createAlarmButtonBox, SIGNAL(accepted()),
            this, SLOT(createNewAlarm()));
    connect(this->createAlarmButtonBox, SIGNAL(rejected()),
            this, SLOT(cancelNewAlarm()));
    connect(this->alarmTimeHourSpinBox, SIGNAL(valueChanged(int)),
            this, SLOT(setAlarmTimeLabel()));
    connect(this->alarmTimeMinuteSpinBox, SIGNAL(valueChanged(int)),
            this, SLOT(setAlarmTimeLabel()));
    connect(this->alarmMessagePreviousComboBox, SIGNAL(activated(QString)),
            this, SLOT(alarmMessagePreviousComboBoxClicked(QString)));
}

void QuickTimer::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
    switch (reason) {
    case QSystemTrayIcon::Trigger:
        if (alarmMessageActive)
            showCurrentAlarmEvent();
        else
            showCreateAlarm();
        break;
    default:
        ;
    }
}

void QuickTimer::setTrayIcon()
{
    if (!alarmMessageActive)
    {
	this->sound->stop();
	this->trayAnimationTimer.stop();
	this->trayIcon->setIcon(this->trayIcons[0]);
    }
    else
    {
	this->trayAnimationIconIndex = 0;
	this->trayAnimationTimer.start(100, this);
    }
    this->updateToolTip();
}

void QuickTimer::messageClicked()
{
    this->processNextAlarmEvent();
}

void QuickTimer::updateToolTip()
{
    QTime currentTime = QTime::currentTime();
    long lowestValue = LONG_MAX;
    Alarm *nextAlarm = 0;
    for (int i = 0; i < alarmList.size(); i++)
    {
        Alarm *alarm = alarmList.at(i);
        if (alarm->getAlarmTime().msecsTo(currentTime) < lowestValue)
            nextAlarm = alarm;
    }

    QString toolTipString = "No Alarm";
    if (nextAlarm)
    {
        toolTipString = "Next Alarm: ";
	toolTipString.append(nextAlarm->getAlarmTime().toString("hh:mm"));
	toolTipString.append("\n");
	toolTipString.append(nextAlarm->getMessage().left(100));
    }
    this->trayIcon->setToolTip(toolTipString);
}

void QuickTimer::alarmMessagePreviousComboBoxClicked(QString message)
{
    this->alarmMessageLineEdit->setText(message);
    this->alarmMessageLineEdit->setFocus();
    this->alarmMessageLineEdit->selectAll();
}

void QuickTimer::writeSettings()
{
    this->settings->beginGroup("AlarmMessages");
    for (int i = 0; i < this->alarmMessageList.size(); i++)
    {
        this->settings->setValue(QString::number(i), alarmMessageList.at(i));
    }
    this->settings->endGroup();
}

void QuickTimer::readSettings()
{
    settings = new QSettings(QSettings::IniFormat, QSettings::UserScope,
                             "code-devils", "QuickTimer");

    this->settings->beginGroup("AlarmMessages");
    for (int i = 0; i < 20; i++)
    {
        QString index = QString::number(i);
        if (this->settings->contains(index))
        {
            this->alarmMessageList.append(this->settings->value(index).toString());
        }
    }
    this->settings->endGroup();

    if (alarmMessageList.isEmpty())
    {
        this->alarmMessageList.append("!!! Alarm !!!");
    }
}
